
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class Nfa {
	final int ESCAPE_SPACE = 127;
	final int ESCAPE_BACK_SLASH = 128;
	final int ESCAPE_ASTERISK = 129;
	final int ESCAPE_PLUS = 130;
	final int ESCAPE_QUESTION = 131;
	final int ESCAPE_OR = 132;
	final int ESCAPE_LEFT_BRACKET = 133;
	final int ESCAPE_RIGHT_BRACKET = 134;
	final int ESCAPE_LEFT_PAREN = 135;
	final int ESCAPE_RIGHT_PAREN = 136;
	final int ESCAPE_PERIOD = 137;
	final int ESCAPE_SINGLE_QUOTE = 138;
	final int ESCAPE_DOUBLE_QUOTE = 139;
	final int ESCAPE_UP_ARROW = 140;
	final int ESCAPE_MINUS = 141;
	final int EPSILON = 142;
	final int IN = 143;

	private String[][] nfa;
	Map<Integer, HashMap<Integer, HashSet<Integer>>> table;
	ArrayList<Integer> columns;
	HashSet<CharClass> characterClasses;

	public Nfa(Map<Integer, HashMap<Integer, HashSet<Integer>>> nfaMap,
			ArrayList<Integer> nfaColumns, HashSet<CharClass> characterClasses) {

		table = nfaMap;
		columns = nfaColumns;
		this.characterClasses = characterClasses;
		/**
		 * Testing purpose only columns.add(97); columns.add(148); table.put(1,
		 * new HashMap<Integer,HashSet<Integer>>()); table.get(1).put(97, new
		 * HashSet<Integer>()); HashSet<Integer> set = table.get(1).get(97);
		 * set.add(2); set.add(4); table.get(1).put(97, set);
		 * 
		 * table.put(2, new HashMap<Integer,HashSet<Integer>>());
		 * table.get(2).put(97, new HashSet<Integer>()); HashSet<Integer> set1 =
		 * table.get(2).get(97); set1.add(5); table.get(2).put(97, set1);
		 */

		nfa = new String[table.size() + 1][columns.size() + 1];

		convertToNfa();

	}

	public void convertToNfa() {
		for (int i = 0; i < columns.size(); i++) {
			if (columns.get(i) >= 32 && columns.get(i) <= 126) {
				char temp = (char) (int) columns.get(i);
				nfa[0][i + 1] = Character.toString(temp);

			} else if (columns.get(i) >= 127 && columns.get(i) < 144) {

				switch (columns.get(i)) {
				case ESCAPE_SPACE:
					nfa[0][i + 1] = " ";
					break;
				case ESCAPE_BACK_SLASH:
					nfa[0][i + 1] = "\\";
					break;
				case ESCAPE_ASTERISK:
					nfa[0][i + 1] = "*";
					break;
				case ESCAPE_PLUS:
					nfa[0][i + 1] = "+";
					break;
				case ESCAPE_QUESTION:
					nfa[0][i + 1] = "?";
					break;
				case ESCAPE_OR:
					nfa[0][i + 1] = "|";
					break;
				case ESCAPE_LEFT_BRACKET:
					nfa[0][i + 1] = "[";
					break;
				case ESCAPE_RIGHT_BRACKET:
					nfa[0][i + 1] = "]";
					break;
				case ESCAPE_LEFT_PAREN:
					nfa[0][i + 1] = "(";
					break;
				case ESCAPE_RIGHT_PAREN:
					nfa[0][i + 1] = ")";
					break;
				case ESCAPE_PERIOD:
					nfa[0][i + 1] = ".";
					break;
				case ESCAPE_SINGLE_QUOTE:
					nfa[0][i + 1] = "'";
					break;
				case ESCAPE_DOUBLE_QUOTE:
					nfa[0][i + 1] = "\"";
					break;
				case ESCAPE_UP_ARROW:
					nfa[0][i + 1] = "^";
					break;
				case ESCAPE_MINUS:
					nfa[0][i + 1] = "-";
					break;
				case EPSILON:
					nfa[0][i + 1] = "EPSILON";
					break;

				}

			} else if (columns.get(i) >= 144) {
				for (CharClass c : characterClasses) {
					if (c.getValue().equals(columns.get(i))) {
						nfa[0][i + 1] = c.getName();
					}
				}
			}
		}

		nfa[0][1] = nfa[0][columns.size()];
		nfa[0][columns.size()] = "EPSILON";
		columns.set(0, columns.get(columns.size() - 1));
		columns.set(columns.size() - 1, EPSILON);

		for (int i = 1; i <= table.size(); i++) {
			nfa[i][0] = "" + i;
			for (Integer input : table.get(i).keySet()) {

				for (int j = 0; j < columns.size(); j++) {

					if (columns.get(j).equals(input)) {

						nfa[i][j + 1] = "";
						int temp = 0;
						for (Integer k : table.get(i).get(columns.get(j))) {
							nfa[i][j + 1] = nfa[i][j + 1] + k;
							temp++;
							if (temp != table.get(i).get(columns.get(j)).size()) {
								nfa[i][j + 1] = nfa[i][j + 1] + ",";
							}

						}

					}
				}
			}
		}
	}

	public String[][] getNfa() {
		return nfa;
	}

	public void setNfa(String[][] nfa) {
		this.nfa = nfa;
	}
}
